<script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue';
import type { UploadFileInfo } from 'naive-ui';
import { useLoadingBar } from 'naive-ui';
import { generateSubtitleFile, parseSubtitle } from '@/utils/subtitle';
import { fetchLanguageOptions } from '@/service/api/language';
import { $t } from '@/locales';

defineOptions({ name: 'TranslationOnline' });

const loadingBar = useLoadingBar();

/** 字幕条目接口 */
interface SubtitleItem {
  /** 字幕ID */
  id: number;
  /** 开始时间 */
  startTime: string;
  /** 结束时间 */
  endTime: string;
  /** 原文内容 */
  text: string;
  /** 翻译内容 */
  translation?: string;
}

/** 源字幕列表 */
const sourceSubtitles = ref<SubtitleItem[]>([]);
/** 翻译后的字幕列表 */
const targetSubtitles = ref<SubtitleItem[]>([]);
/** 翻译加载状态 */
const loading = ref(false);

/** 表单数据 */
const formData = reactive({
  /** 目标语言 */
  targetLang: '',
  /** 上传的字幕文件 */
  file: null as File | null
});

/** 语言选项接口 */
interface LanguageOption {
  name: string; // 语言描述
  value: string; // 语言代码
}

/** 可选的目标语言列表 */
const langOptions = ref<{ label: string; value: string }[]>([]);

/**
 * 获取支持的翻译语言选项
 * @description 从后端获取支持的语言列表,过滤掉已设置跳过的语言
 */
async function getLangOptions() {
  try {
    const { data } = await fetchLanguageOptions();
    // 按语言名称排序
    const sortedData = (data as LanguageOption[]).sort((a, b) =>
      a.name.localeCompare(b.name)
    );
    langOptions.value = sortedData.map((item) => ({
      label: item.name,
      value: item.value
    }));
    // 设置默认语言为英语(如果存在)，否则选择第一个
    const defaultLang =
      langOptions.value.find((item) => item.value === 'en') ||
      langOptions.value[0];
    if (defaultLang) {
      formData.targetLang = defaultLang.value;
    }
  } catch {
    window.$message?.error($t('page.translation.messages.getLangFailed'));
  }
}

// 组件挂载时获取语言选项
onMounted(() => {
  getLangOptions();
});

/**
 * 处理字幕文件上传
 * @description 读取上传的.srt文件内容并解析为字幕数组
 */
function handleFileUpload(data: {
  file: UploadFileInfo;
  fileList: UploadFileInfo[];
}) {
  if (!data || !data.file) {
    return;
  }

  // 获取原始文件对象
  const file = data.file.file;
  if (!file) {
    window.$message?.error($t('page.translation.messages.invalidFile'));
    return;
  }

  // 验证文件类型
  if (!file.name.toLowerCase().endsWith('.srt')) {
    window.$message?.warning($t('page.translation.messages.invalidFileType'));
    return;
  }

  // 重置之前的数据
  resetSubtitles();
  formData.file = file;

  // 读取字幕文件内容
  const reader = new FileReader();
  reader.onload = (e) => {
    const content = e.target?.result as string;
    try {
      // 解析字幕内容为数组
      sourceSubtitles.value = parseSubtitle(content);
      if (sourceSubtitles.value.length === 0) {
        throw new Error('No subtitles found');
      }
      // 如果还没有选择目标语言，自动选择默认语言
      if (!formData.targetLang && langOptions.value.length > 0) {
        const defaultLang =
          langOptions.value.find((item) => item.value === 'en') ||
          langOptions.value[0];
        formData.targetLang = defaultLang.value;
      }
      window.$message?.success($t('page.translation.messages.parseSuccess'));
    } catch {
      window.$message?.error($t('page.translation.messages.parseFailed'));
      sourceSubtitles.value = [];
      formData.file = null;
    }
  };
  reader.onerror = () => {
    window.$message?.error($t('page.translation.messages.readFailed'));
    formData.file = null;
  };
  reader.readAsText(file);
}

/**
 * 开始翻译处理
 * @description 将解析后的字幕发送到后端进行翻译
 */
async function handleTranslate() {
  if (!formData.file || !sourceSubtitles.value.length) {
    window.$message?.warning($t('page.translation.messages.noFile'));
    return;
  }

  loadingBar.start();
  loading.value = true;
  try {
    // const { data } = await translateSubtitle({
    //   subtitles: sourceSubtitles.value,
    //   targetLang: formData.targetLang
    // });
    // if (data)
    //   targetSubtitles.value = data ?? [];
    window.$message?.success($t('page.translation.messages.translateSuccess'));
  } catch {
    window.$message?.error($t('page.translation.messages.translateFailed'));
  } finally {
    loadingBar.finish();
    loading.value = false;
  }
}

/**
 * 更新翻译内容
 * @description 用户手动修改翻译结果时触发
 * @param index 字幕索引
 * @param value 新的翻译内容
 */
function updateTranslation(index: number, value: string) {
  if (targetSubtitles.value[index]) {
    targetSubtitles.value[index].translation = value;
  }
}

/**
 * 下载翻译结果
 * @description 将翻译后的字幕内容导出为.srt文件
 */
function downloadTranslation() {
  if (!targetSubtitles.value.length) {
    window.$message?.warning($t('page.translation.messages.noContent'));
    return;
  }

  const content = generateSubtitleFile(targetSubtitles.value);
  const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
  const url = URL.createObjectURL(blob);

  const link = document.createElement('a');
  link.href = url;
  link.download = `translation_${formData.targetLang}.srt`;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
}

/** 检查字幕是否已翻译
 * @param id 字幕ID
 * @returns 是否已翻译
 */
function hasTranslation(id: number): boolean {
  const target = targetSubtitles.value.find((item) => item.id === id);
  return Boolean(target?.translation);
}

/** 重置字幕数据 */
function resetSubtitles() {
  sourceSubtitles.value = [];
  targetSubtitles.value = [];
  formData.file = null;
}

/** 移除当前文件 */
function removeFile() {
  if (loading.value) return;
  resetSubtitles();
  window.$message?.success($t('page.translation.messages.fileRemoved'));
}
</script>

<template>
  <div class="h-full flex-col gap-15px p-15px">
    <!-- 顶部操作区 -->
    <NCard
      :title="$t('page.translation.title')"
      class="flex-shrink-0 card-shadow"
    >
      <!-- 帮助提示 -->
      <template #header-extra>
        <NSpace>
          <NTooltip placement="bottom" trigger="hover">
            <template #trigger>
              <NButton
                circle
                class="hover:text-primary hover:bg-primary-1"
                quaternary
              >
                <IconMaterialSymbolsHelpOutline />
              </NButton>
            </template>
            {{ $t('page.translation.uploadTip') }}
          </NTooltip>
        </NSpace>
      </template>

      <!-- 操作按钮组 -->
      <NSpace vertical>
        <div
          class="flex items-center gap-15px flex-wrap p-20px bg-content rounded-lg transition-all"
        >
          <!-- 文件上传 -->
          <NUpload
            :directory="false"
            :disabled="loading"
            :max="1"
            :multiple="false"
            :show-file-list="false"
            accept="'.srt,.ass,.ssa'"
            @change="handleFileUpload"
          >
            <NButton
              :class="{ 'opacity-50': loading }"
              :disabled="loading"
              :type="sourceSubtitles.length ? 'default' : 'primary'"
              class="min-w-120px shadow-sm hover:shadow-md transition-all"
              ghost
            >
              <!--              <template #icon>-->
              <!--                <icon-material-symbols:upload-->
              <!--                  class="transition-transform group-hover:-translate-y-1"-->
              <!--                />-->
              <!--              </template>-->
              {{ $t('page.translation.upload') }}
            </NButton>
          </NUpload>

          <!-- 目标语言选择 -->
          <NSelect
            v-model:value="formData.targetLang"
            :consistent-menu-width="false"
            :disabled="loading || !sourceSubtitles.length"
            :loading="!langOptions.length"
            :options="langOptions"
            :placeholder="$t('page.translation.targetLang')"
            :show-arrow="true"
            class="w-200px !flex-shrink-0 min-w-200px shadow-sm transition-all select-input"
            clearable
            filterable
          />

          <!-- 翻译按钮 -->
          <NButton
            :class="{
              'opacity-50': !sourceSubtitles.length || !formData.targetLang,
            }"
            :disabled="!sourceSubtitles.length || !formData.targetLang"
            :loading="loading"
            class="min-w-120px shadow-sm hover:shadow-md transition-all group"
            type="primary"
            @click="handleTranslate"
          >
            <template #icon>
              <IconMaterialSymbolsTranslate
                class="transition-transform group-hover:rotate-12"
              />
            </template>
            {{ $t('page.translation.translate') }}
          </NButton>

          <!-- 当前文件名显示 -->
          <div
            v-if="formData.file"
            :title="formData.file.name"
            class="flex items-center gap-8px text-text truncate max-w-400px bg-card/80 px-12px py-6px rounded-md transition-all group relative"
          >
            <IconMaterialSymbolsDescriptionOutline
              class="text-16px text-primary"
            />
            {{
              $t('page.translation.currentFile', { name: formData.file.name })
            }}
            <!-- 移除文件按钮 -->
            <div
              class="absolute right-0 top-0 bottom-0 w-32px flex-center bg-gradient-to-l from-card/95 via-card/95 opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer"
              @click="removeFile"
            >
              <NButton
                :disabled="loading"
                circle
                class="hover:text-error"
                quaternary
                size="small"
              >
                <template #icon>
                  <IconMaterialSymbolsClose />
                </template>
              </NButton>
            </div>
          </div>
        </div>
      </NSpace>
    </NCard>

    <!-- 字幕内容区 -->
    <div class="flex-1 flex gap-15px min-h-0">
      <!-- 源字幕显示 -->
      <NCard
        :title="$t('page.translation.sourceSubtitle')"
        class="flex-1 min-w-0 card-shadow"
      >
        <template #header-extra>
          <span
            class="text-text text-sm font-medium bg-content px-8px py-4px rounded"
          >
            {{
              $t('page.translation.totalCount', {
                count: sourceSubtitles.length
              })
            }}
          </span>
        </template>
        <div class="h-full overflow-auto px-4 py-4 subtitle-content">
          <div v-for="item in sourceSubtitles" :key="item.id" class="mb-15px">
            <div class="text-secondary text-sm mb-4px font-mono">
              {{ item.startTime }} --> {{ item.endTime }}
            </div>
            <div
              :class="[
                hasTranslation(item.id)
                  ? 'bg-success-hover'
                  : 'bg-content hover:bg-content-hover',
              ]"
              class="p-12px rounded-lg transition-all hover:shadow-sm"
            >
              <div
                :class="[
                  hasTranslation(item.id) ? 'text-success' : 'text-primary',
                ]"
                class="transition-colors"
              >
                {{ item.text }}
              </div>
            </div>
          </div>
          <div
            v-if="!sourceSubtitles.length"
            class="h-full flex-center text-secondary"
          >
            <div class="flex-col items-center gap-8px">
              <IconMaterialSymbolsSubtitlesOutline
                class="text-32px mb-12px text-primary opacity-50"
              />
              {{ $t('page.translation.messages.noFile') }}
            </div>
          </div>
        </div>
      </NCard>

      <!-- 翻译结果显示 -->
      <NCard
        :title="$t('page.translation.targetSubtitle')"
        class="flex-1 min-w-0 shadow-sm"
      >
        <template #header-extra>
          <NSpace>
            <span
              class="text-gray-500 text-sm font-medium bg-gray-50 px-8px py-4px rounded"
            >
              {{
                $t('page.translation.totalCount', {
                  count: targetSubtitles.length
                })
              }}
            </span>
            <!-- 下载按钮 -->
            <NButton
              :disabled="!targetSubtitles.length"
              class="min-w-100px shadow-sm hover:shadow-md transition-all group"
              secondary
              type="success"
              @click="downloadTranslation"
            >
              <template #icon>
                <IconMaterialSymbolsDownload
                  class="transition-transform group-hover:translate-y-1"
                />
              </template>
              {{ $t('page.translation.download') }}
            </NButton>
          </NSpace>
        </template>

        <!-- 翻译结果编辑区 -->
        <div class="h-full overflow-auto px-4 py-4">
          <div
            v-for="(item, index) in targetSubtitles"
            :key="item.id"
            class="mb-15px"
          >
            <div class="text-gray-400 text-sm mb-4px font-mono">
              {{ item.startTime }} --> {{ item.endTime }}
            </div>
            <NInput
              v-model:value="item.translation"
              :disabled="loading"
              :placeholder="$t('page.translation.placeholder')"
              :rows="2"
              :status="item.translation ? 'success' : undefined"
              class="hover:shadow-sm focus:shadow-md transition-all subtitle-input"
              type="textarea"
              @update:value="updateTranslation(index, $event)"
            />
          </div>
          <div
            v-if="!targetSubtitles.length"
            class="h-full flex-center text-gray-400"
          >
            {{ $t('page.translation.messages.noFile') }}
          </div>
        </div>
      </NCard>
    </div>
  </div>
</template>

<style scoped>
/* 卡片布局样式 */
.n-card {
  display: flex;
  flex-direction: column;
  border: none;
  transition: all 0.3s ease;
}

/* 卡片头部样式 */
:deep(.n-card-header) {
  flex-shrink: 0;
  padding: 16px 20px;
}

/* 卡片内容区样式 */
:deep(.n-card__content) {
  flex: 1;
  overflow: hidden;
  padding: 16px;
}

/* 滚动条样式 */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  border-radius: 3px;
}

/*
::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-hover-color);
}

// 输入框样式覆盖
:deep(.n-input) {
  background: var(--card-bg-color);
}
*/

/* 字幕输入框样式 */
:deep(.subtitle-input) {
  .n-input__textarea {
    transition: all 0.3s ease;
  }

  &:not(.n-input--disabled) {
    .n-input__textarea:hover {
      background-color: #ffffff;
    }
  }

  &.n-input--success {
    .n-input__textarea {
      background-color: rgba(0, 128, 0, 0.03);
    }
  }
}

/* 下拉菜单样式覆盖 */
:deep(.n-select-menu) {
  max-height: 300px;
}

/* 工具类 */
.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 语言选择器样式 */
:deep(.select-input) {
  .n-base-selection {
    transition: all 0.3s ease;
  }

  &:not(.n-select--disabled) {
    .n-base-selection:hover {
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    }
  }

  /* 选择框聚焦状态 */

  .n-base-selection--focused {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) !important;
  }
}

/* 字幕内容区域样式 */
.subtitle-content {
  scrollbar-gutter: stable;
}

/* 语言选择器样式 */
:deep(.select-input) {
  .n-base-selection {
    transition: all 0.3s ease;
  }

  &:not(.n-select--disabled) {
    .n-base-selection:hover {
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    }
  }

  /* 选择框聚焦状态 */

  .n-base-selection--focused {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) !important;
  }
}

/* 字幕输入框样式 */
:deep(.subtitle-input) {
  .n-input__textarea {
    transition: all 0.3s ease;
  }

  &:not(.n-input--disabled) {
    .n-input__textarea:hover {
      background-color: #ffffff;
    }
  }

  &.n-input--success {
    .n-input__textarea {
      background-color: rgba(0, 128, 0, 0.03);
    }
  }

  /* 输入框聚焦状态 */

  .n-input--focus {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) !important;
  }
}
</style>
